---
title: User Authorization
---

The assistant-ui API can be directly accessed by your frontend. This elliminates the need for a backend server from your side, except for authorization of your users.

This document explains how you can setup your server to authorize users to access the assistant-ui API.

## Workspaces

Authorization is granted to a workspace. Depending on the structure of your app, you might want to use user_ids as the workspace_id, or you might want to use a more complex structure.
For example, if your app supports multiple "projects", you might want to use the project_id + user_id as the workspace id (thread history scoped to user+project pairs).

## Workspace Auth Tokens

assistant-ui issues workspace auth tokens. These tokens give access to the assistant-ui API for a specific workspace.
Tokens are short lived (5 minutes), so the client needs to periodically request a new token (handled by assistant-ui).

There are two supported approaches to obtain a workspace auth token:

- Direct integration with your auth provider
- From a backend server / serverless function

### Choosing the right approach

Direct integration with your auth provider:

- simpler to setup and maintain
- assigns a workspace_id to every user (by using the user_id as the workspace_id)
- requires a supported auth provider (Clerk, Auth0, Supabase, Firebase, Stytch, Kinde, ...)

Backend server:

- more complex to setup
- more flexible workspace structure (multi-user workspaces, workspaces per project, etc.)
- supports self hosted auth solutions, e.g. Auth.js
- requires a backend server / serverless function

You can always switch between the two approaches without any downtime or necessary database migrations.
Choose direct integration with your auth provider if you can. Otherwise, use a backend server.

### Auth Provider Integration
In the AssistantUI dashboard, go to the "Auth Integrations" tab and add a new integration.
Follow the steps to add your auth provider. (See the auth providers we have guides for at the bottom of this page.)

Then, pass in a function to `authToken` that returns an ID token from your auth provider.

```ts
import { AssistantCloud } from "@assistant-ui/react";

const assistantCloud = new AssistantCloud({
  authToken: () => JWT_TOKEN
});
```

### Integration with an Auth Provider

#### Backend API Endpoint

The following is an api route example to create an auth token based on an authenticated user's orgId and userId.

In the Assistant Cloud dashboard, go to the "API Keys" tab and add a new API key, add the key the environment variable `ASSISTANT_API_KEY=[KEY]`

```ts title="/app/api/assistant-ui-token/route.ts"
import { AssistantCloud } from "@assistant-ui/react";
import { auth } from "@clerk/nextjs/server";
 
export const POST = async (req: Request) => {
  const { userId, orgId } = await auth();
 
  if (!userId) throw new Error("User not authenticated");
 
  const workspaceId = orgId ? `${orgId}_${userId}` : userId;
  const assistantCloud = new AssistantCloud({
    apiKey: process.env["ASSISTANT_API_KEY"]!,
    userId,
    workspaceId,
  });
  const {token} = await assistantCloud.auth.tokens.create();

  return new Response(token);
};
```

#### Frontend Implementation

The following is an api route example to create an auth token based on an authenticated user's orgId and userId.

```ts title="client.ts"
const cloud = new AssistantCloud({
  baseUrl: process.env["NEXT_PUBLIC_ASSISTANT_BASE_URL"]!,
  authToken: () =>
    fetch("/api/assistant-ui-token", { method: "POST" }).then((r) =>
      r.text(),
    ),
});

const runtime = useChatRuntime({
  api: "/api/chat",
  cloud,
});
```

### Anonymous (without auth provider) Frontend Implementation

The following is a example to get auth tokens for Clerk based on the org_id and user_id:

```ts title="/app/api/assistant-ui-token/route.ts"
import { AssistantCloud } from "@assistant-ui/react";

const cloud = new AssistantCloud({
  baseUrl: process.env["NEXT_PUBLIC_ASSISTANT_BASE_URL"]!,
  anonymous: true,
});

const runtime = useChatRuntime({
  api: "/api/chat",
  cloud,
});

return (
  <AssistantRuntimeProvider runtime={runtime}>
    <div className="grid h-dvh grid-cols-[200px_1fr] gap-x-2 px-4 py-4">
      <ThreadList />
      <MyThread />
    </div>
  </AssistantRuntimeProvider>
);

```


### Setting up the Clerk Auth Provider

First, go to the Clerk dashboard and under "Configure" tab, "JWT Templates" section, create a new template. Choose a blank template and name it "assistant-ui".

As the "Claims" field, enter the following:

```json
{
  "aud": "assistant-ui"
}
```

<Callout emoji="⚠️">
  <b>Note:</b> The aud claim ensures that the JWT is only valid for the
  assistant-ui API.
</Callout>

You can leave everything else as default. Take note of the "Issuer" and "JWKS Endpoint" fields.

Then, In the assistant-cloud dashboard, navigate to the "Auth Rules" tab and create a new rule. Choose "Clerk" and enter the Issuer and JWKS Endpoint from the previous step. As the "Audience" field, enter "assistant-ui".
